package lab.anoper.fsm.fsm;

import org.squirrelframework.foundation.fsm.StateMachineBuilderFactory;
import org.squirrelframework.foundation.fsm.UntypedStateMachine;
import org.squirrelframework.foundation.fsm.UntypedStateMachineBuilder;
import org.squirrelframework.foundation.fsm.annotation.StateMachineParameters;
import org.squirrelframework.foundation.fsm.impl.AbstractUntypedStateMachine;

/**
 * @author Yan Jiahong
 * Created at 2020/9/29
 */

@StateMachineParameters(stateType = PayOrderState.class, eventType = PayOrderEvent.class, contextType = WxpayOrder.class)
public class PayOrderStateMachine extends AbstractUntypedStateMachine implements UntypedStateMachine {
    protected void fromCreatedToPaying(PayOrderState from, PayOrderState to, PayOrderEvent event, WxpayOrder order) {
        System.out.printf("Transition from [%s] to [%s] on event [%s] with context [%s]",
                from, to, event, order
        );
    }

    protected void fromPayingToPaySuccess(PayOrderState from, PayOrderState to, PayOrderEvent event, WxpayOrder order) {
        System.out.printf("Transition from [%s] to [%s] on event [%s] with context [%s]",
                from, to, event, order
        );
    }

    protected void fromPayingToPayFailed(PayOrderState from, PayOrderState to, PayOrderEvent event, WxpayOrder order) {
        System.out.printf("Transition from [%s] to [%s] on event [%s] with context [%s]",
                from, to, event, order
        );
    }

    protected void fromPayFailToPaying(PayOrderState from, PayOrderState to, PayOrderEvent event, WxpayOrder order) {
        System.out.printf("Transition from [%s] to [%s] on event [%s] with context [%s]",
                from, to, event, order
        );
    }

    protected void onEntryCreated(PayOrderState from, PayOrderState to, PayOrderEvent event, WxpayOrder order) {
        System.out.printf("entry from [%s] to [%s] on event [%s] with context [%s]",
                from, to, event, order
        );
    }

    public static void main(String[] args) {
        WxpayOrder payOrder = new WxpayOrder();
        UntypedStateMachineBuilder builder = StateMachineBuilderFactory.create(PayOrderStateMachine.class);
//        builder.onEntry(PayOrderState.CREATED).callMethod("");
        builder.externalTransition().from(PayOrderState.CREATED).to(PayOrderState.PAYING)
                .on(PayOrderEvent.PAY_APPLY_SUCCESS).callMethod("fromCreatedToPaying");
        UntypedStateMachine payOrderFSM = builder.newStateMachine(PayOrderState.CREATED);
        payOrderFSM.fire(PayOrderEvent.PAY_APPLY_SUCCESS, payOrder);

        System.out.println("现在的状态是: " + payOrderFSM.getCurrentState());
    }

//    /**
//     * 支付订单
//     *
//     * @param order 支付订单实例
//     * @return 支付订单状态机
//     */
//    public static UntypedStateMachine getStartedInstance(WxpayOrder order) {
//        if (order == null || order.getStatus() == null) {
//            throw new IllegalArgumentException("订单不能为null且订单状态不能为null, order=" + order);
//        }
//        UntypedStateMachine fsm = getStartedInstance();
//        fsm.fire(order.getStatus());
//        return fsm;
//    }

    public static UntypedStateMachine getStartedInstance(WxpayOrder order) {
        UntypedStateMachineBuilder builder = StateMachineBuilderFactory.create(PayOrderStateMachine.class);
        // 已创建转移到支付申请成功
        builder.externalTransition().from(PayOrderState.CREATED).to(PayOrderState.PAYING)
                .on(PayOrderEvent.PAY_APPLY_SUCCESS).callMethod("fromCreatedToPaying");
        // 支付申请成功转移到支付成功
        builder.externalTransition().from(PayOrderState.PAYING).to(PayOrderState.PAY_SUCCESS)
                .on(PayOrderEvent.PAY_SUCCESS).callMethod("fromPayingToPaySuccess");
        // 支付申请成功转移到支付失败
        builder.externalTransition().from(PayOrderState.PAYING).to(PayOrderState.PAY_FAIL)
                .on(PayOrderEvent.PAY_FAILED).callMethod("fromPayingToPayFail");
        // 从支付失败转移到支付成功
        builder.externalTransition().from(PayOrderState.PAY_FAIL).to(PayOrderState.PAYING)
                .on(PayOrderEvent.PAY_APPLY_SUCCESS).callMethod("fromCreatedToPaying");

        builder.onEntry(PayOrderState.CREATED).callMethod("onEntryCreated");
        UntypedStateMachine fsm = builder.newStateMachine(order.getStatus());
        fsm.start(order);
        return fsm;
    }
}
